package org.softmed.action.guice;

import groovy.lang.GroovyClassLoader;
import groovy.util.GroovyScriptEngine;

import java.io.IOException;
import java.util.List;

import org.softmed.action.builder.ActionCreator;
import org.softmed.action.builder.DefaultActionCreator;
import org.softmed.action.converter.ActionDescriptionXMLConverter;
import org.softmed.action.converter.DefaultXStreamActionConverter;
import org.softmed.action.implementation.DefaultGroovyClassActionStepResolver;
import org.softmed.action.implementation.DefaultGroovyScriptActionStepResolver;
import org.softmed.action.implementation.DefaultJavaActionStepResolver;
import org.softmed.action.resolver.ActionResolver;
import org.softmed.action.resolver.ActionStepResolver;
import org.softmed.action.resolver.DefaultActionResolver;
import org.softmed.filehandling.FileUtil;
import org.softmed.filehandling.selectors.GroovyFileSelector;
import org.softmed.groovy.utils.GroovyCache;

import com.google.inject.Binder;
import com.google.inject.Module;
import com.google.inject.TypeLiteral;

public class ActionModule implements Module {

	GroovyScriptEngine groovyScriptEngine = null;

	GroovyClassLoader groovyClassLoader = null;

	GroovyCache groovyCache = null;

	public ActionModule() {

	}

	public ActionModule(GroovyClassLoader groovyClassLoader,
			GroovyScriptEngine groovyScriptEngine, GroovyCache groovyCache) {
		this.groovyClassLoader = groovyClassLoader;
		this.groovyScriptEngine = groovyScriptEngine;
		this.groovyCache = groovyCache;
	}

	@Override
	public void configure(Binder binder) {

		binder.bind(ActionStepResolver.class).annotatedWith(
				new NamedAnnotation("JavaResolver")).to(
				DefaultJavaActionStepResolver.class);
		binder.bind(ActionStepResolver.class).annotatedWith(
				new NamedAnnotation("GroovyClassResolver")).to(
				DefaultGroovyClassActionStepResolver.class);
		binder.bind(ActionStepResolver.class).annotatedWith(
				new NamedAnnotation("GroovyResolver")).to(
				DefaultGroovyScriptActionStepResolver.class);

		binder.bind(new TypeLiteral<List<ActionStepResolver>>() {
		}).toProvider(SpecificActioStepResolverProvider.class)
				.asEagerSingleton();

		binder.bind(ActionDescriptionXMLConverter.class).to(
				DefaultXStreamActionConverter.class);

		binder.bind(ActionResolver.class).to(DefaultActionResolver.class);

		binder.bind(ActionCreator.class).to(DefaultActionCreator.class);

		if (groovyClassLoader == null) {
			groovyClassLoader = new GroovyClassLoader(this.getClass()
					.getClassLoader());
			// groovyClassLoader.setShouldRecompile(true);
			GroovyFileSelector.setGroovyClassLoader(groovyClassLoader);
			binder.bind(GroovyClassLoader.class).toInstance(groovyClassLoader);
		}

		if (groovyScriptEngine == null) {
			FileUtil util = new FileUtil();
			String[] roots = new String[] { util.getRootPath() };
			try {
				groovyScriptEngine = new GroovyScriptEngine(roots);
				binder.bind(GroovyScriptEngine.class).toInstance(
						groovyScriptEngine);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		if (groovyCache == null) {
			GroovyCache.setGroovyClassLoader(groovyClassLoader);
			// GroovyCache.setGroovyScriptEngine(groovyScriptEngine);
			groovyCache = new GroovyCache();
			binder.bind(GroovyCache.class).toInstance(groovyCache);
		}

		//		

	}

	public GroovyScriptEngine getGroovyScriptEngine() {
		return groovyScriptEngine;
	}

	public GroovyClassLoader getGroovyClassLoader() {
		return groovyClassLoader;
	}

	public void setGroovyScriptEngine(GroovyScriptEngine groovyScriptEngine) {
		this.groovyScriptEngine = groovyScriptEngine;
	}

	public void setGroovyClassLoader(GroovyClassLoader groovyClassLoader) {
		this.groovyClassLoader = groovyClassLoader;
	}

}
